Middleware 是client端和controller之間的橋樑.它可以攔截存取request和respond.Middleware可以有多個,彼此之間透過next()連結.Middleware可以用於許多任務,包括:
Class Middleware是NestJS預設情況下使用的種類,建立方式如下:
$nest g middleware <MIDDLEWARE_NAME>
產生的框架如下:
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: any, res: any, next: ()=>void {
console.log('Request...');
next();
}
}
解釋說明:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('cats');
}
}
解釋說明:
1.使用implements讓AppModule去實作NestModule
2.使用configure()方法,裡面的參數型別是MiddlewareConsumer
3.透過consumer的**apply()方法,去註冊我們自己設計的LoggerMiddleware
4.再透過forRoutes()**方法,去指定哪個路由有效,這個範例,只要前綴為cats的都會有效
5.補充第4點,或是可以在forRoutes中改成CatsController(上方記得import),這樣就能針對整個Controller底下的Handler做套用了
*關於configure():https://expressjs.com/2x/guide.html#app.configure()
使用逗號隔開不同的Middleware,要特別注意順序會有影響,先寫的Middleware會先執行
修改範例如下:consumer.apply(CheckerMiddleware,LoggerMiddleware).forRoutes(CatsController);
此時就會先執行CheckerMiddleware再執行LoggerMiddleware.
如果想針對多個不同路由或是某個特定的api去做套用.那就可以在forRoutes()中做指定,在forRoutes中設置兩個物件格式分別是path和method,path代表路由前綴,method代表需要符合的http code.而當兩個都符合條件時,才會被套用.
修改範例如下:forRoutes({ path: 'ab*cd', method: RequestMethod.Get }, { path: '/', method: RequestMethod.Get }, );
解釋說明:
只有前綴為ab開頭cd結尾,並且符合get方法的api以及沒有前綴且符合get方法的api才會套用api
和套用指定路由正好相反,只需要透過consumer底下的**exclude()**方法來針對符合條件的api做排除.
配置條件方法和指定路由條件一樣,設置物件格式分別為path和method
修改範例如下:
consumer
.apply(LoggerMiddleware)
.exclude(
{ path: 'cats', method: RequestMethod.GET },
{ path: 'cats', method: RequestMethod.POST },
)
.forRoutes(CatsController);
解釋說明:
我們排除掉cats路由中使用get和post方法的api,並套用在CatsController上.
如果想將Middleware套用在每一個路由上的話,有兩種方法:
直接在main.ts中使用app.use()
範例如下:
const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
在app.module.ts實作NestModule的介面中,forRoutes()的指定路由為*即可
範例如下:
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*');
}